package main

// <----------------------------------------- 协程框架 -------------------------------------------->

import (
	"database/sql"
	"fmt"
	"runtime"
)

var (
	//Max_Num = os.Getenv("MAX_NUM")
	MaxWorker = runtime.NumCPU() //  协程的CPU数量
	MaxQueue  = 1000             // 工作队列
)

type Serload struct {
	bodyContent []byte
	dbs         *sql.DB
}

// 定义工作结构体
type Job struct {
	serload Serload
}

var dbs *sql.DB

var JobQueue chan Job // 声明一个任务队列，用通道：（通道本身就是先进先出的队列）

/*****************************************************  工作者内容    ****************************************************************/
// 定义工作者
type Worker struct {
	WorkId     int
	WorkerPool chan chan Job // 工人对象池
	JobChannel chan Job      // 管道里面拿job
	Quit       chan bool
}

// 新建一个工作者
func NewWorker(workPool chan chan Job, workid int) Worker {

	return Worker{
		WorkId:     workid,
		WorkerPool: workPool,
		JobChannel: make(chan Job),
		Quit:       make(chan bool),
	}

}

// 工作池启动函数
func (w Worker) Start() {
	// 开一个新的协程
	go func() {
		for {
			// 注册任务到工作池
			w.WorkerPool <- w.JobChannel
			select {
			// 接受任务
			case job := <-w.JobChannel:
				// 执行任务 job
				fmt.Println(w.WorkId, "   working")

				// fmt.Printf("在函数中：%d\n", job.serload.res)
				CoroutineWork(job.serload.bodyContent, job.serload.dbs)

			// 接收退出的任务，停止任务
			case <-w.Quit:
				return
			}
		}
	}()
}

// 退出执行工作
func (w Worker) Stop() {
	go func() {
		w.Quit <- true
	}()
}

/*********************************************************    适配器内容    ***********************************************************/

// 定义任务发送者
type Dispatcher struct {
	MaxWorkers int           // 最大工人数
	WorkerPool chan chan Job // 注册工作通道
	Quit       chan bool     // 退出信号
}

// 注册新发送者
func NewDispatcher(maxWorkers int) *Dispatcher {
	pool := make(chan chan Job, maxWorkers)
	return &Dispatcher{MaxWorkers: maxWorkers, WorkerPool: pool, Quit: make(chan bool)}
}

// 工作分发器
func (d *Dispatcher) Run() {
	for i := 0; i < d.MaxWorkers; i++ {
		fmt.Println("new worker", i) // 这里是结果显示处
		worker := NewWorker(d.WorkerPool, i)
		worker.Start()
	}
	// 监控任务发送 - 协程
	go d.Dispatch()
}

// 退出分发任务
func (d *Dispatcher) Stop() {
	go func() {
		d.Quit <- true
	}()
}

// 调度器
func (d *Dispatcher) Dispatch() {
	for {
		select {
		// 接收到任务
		case job := <-JobQueue: // 从任务队列取出任务
			go func(job Job) {
				jobChannel := <-d.WorkerPool // 取出一个工作线程的通道
				jobChannel <- job            // 发送任务到指定通道
			}(job) // (匿名函数，job是我们传进去的值)
		case <-d.Quit:
			return
		}
	}
}
